package com.rockcent.wechat.controller;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.rockcent.common.common.JsonResult;
import com.rockcent.common.common.PageResult;
import com.rockcent.common.common.RestDoing;
import com.rockcent.common.controller.BaseController;
import com.rockcent.common.domain.enumclass.Whether;
import com.rockcent.common.utils.BigDecimalUtils;
import com.rockcent.common.utils.RBeanUtils;
import com.rockcent.mall.lib.domain.*;
import com.rockcent.mall.lib.domain.enumclass.*;
import com.rockcent.mall.lib.dto.*;
import com.rockcent.mall.lib.helper.ProductEventHelper;
import com.rockcent.mall.lib.repository.*;
import com.rockcent.service.ProductSrv;
import com.rockcent.wechat.Routes;
import com.rockcent.wechat.helper.CustomerHelper;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.text.NumberFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * Created by zhangjh on 2016/10/8.
 */
@RestController
@RequestMapping(value = Routes.API_PREFIX)
public class ProductController extends BaseController {
    private static final Logger log = LoggerFactory.getLogger(ProductController.class);


    @Autowired
    private MerchantProductRepository merchantProductRepository;
    @Autowired
    private MallRepository mallRepository;
    @Autowired
    private EvaluationRepository evaluationRepository;
    @Autowired
    private MerchantProductDetailRepository merchantProductDetailRepository;
    @Autowired
    private CustomerRepository customerRepository;
    @Autowired
    private ProductEventRepository productEventRepository;
    @Autowired
    private ProductEventHelper productEventHelper;
    @Autowired
    private ChannelRepository channelRepository;
    @Autowired
    private FavoriteRepository favoriteRepository;
    @Autowired
    private MerchantRepository merchantRepository;
    @Autowired
    private CustomerHelper customerHelper;
    @Autowired
    private MerchantCouponRepository merchantCouponRepository;
    @Autowired
    private ObjectMapper objectMapper;
    @Autowired
    private CouponMerchantProductsRepository couponMerchantProductsRepository;
    @Autowired
    private MerchantOrderRepository merchantOrderRepository;
    @Autowired
    private MerchantProductCategoriesRepository merchantProductCategoriesRepository;
    @Autowired
    private MerchantOrderItemRepository merchantOrderItemRepository;
    @Autowired
    private ProductQuantityRepository productQuantityRepository;
    @Autowired
    private ProductSrv productSrv;
    @Autowired
    private MallFinancialSettingsRepository mallFinancialSettingsRepository;

    /**
     * @api {get} /api/v2/product/search 查找产品
     * @apiGroup product
     * @apiVersion 1.0.0
     * @apiParam {String} keyword 关键词
     * @apiParam {String} orderBy 排序字段：saleCount（销量降序），sellPrice（售价），ALL（综合）
     * @apiParam {String} sort 排序方式，desc（降序），asc（升序）
     * @apiParam {Integer} pageNo 页码
     * @apiParam {Integer} pageSize 每页记录数
     * @apiSuccess {Long} id ID
     * @apiSuccess {Date} dateCreated 创建时间
     * @apiSuccess {Date} lastUpdated 更新时间
     * @apiSuccess {Long} version 版本
     * @apiSuccess {String} identifier 产品唯一的识别码
     * @apiSuccess {String} name 名称
     * @apiSuccess {String} type 类型 ALL("全部"), GOODS("商品"), SERVICE("服务")
     * @apiSuccess {BigDecimal} basePrice 原价
     * @apiSuccess {BigDecimal} sellPrice 售价
     * @apiSuccess {Long} quantity 库存数量
     * @apiSuccess {BigDecimal} carriage 运费
     * @apiSuccess {Boolean} refundable 是否支持过期退
     * @apiSuccess {Boolean} sellnow 是否立即开售
     * @apiSuccess {Date} dateSelling 开售时间
     * @apiSuccess {Long} limitCount 限购数量
     * @apiSuccess {String} logoUrl LOGO图
     * @apiSuccess {String} note 卖点介绍
     * @apiSuccess {String} status 状态 SELLING("在售"), SUPPLIER_CANCEL_SOLDOUT("分销市场 供应商取消供货 已下架"),DISTRIBUTOR_CANCEL_SOLDOUT("分销市场 分销商取消代销 已下架"), SOLDOUT("已下架"), EXPIRED("已过期"), DELETED("已删除"), WAIT_APPLY("待申请"), WAIT_AUDIT("待审核"), AUDIT_PASS("审核通过"), AUDIT_FAIL("审核不通过")
     * @apiSuccess {Long} mallId 商城 id
     * @apiSuccess {Long} merchantId 商家 id
     * @apiSuccess {String} serveRate 服务费比率
     * @apiSuccess {String} shippingType 支持的物流类型 SHOP_PICKUP("到店自取"), SHIPPING("物流"), SHOP_PICKUP_AND_SHIPPING("物流及到店自取")
     * @apiSuccess {BigDecimal} resellFee 分销佣金
     * @apiSuccess {BigDecimal} shareFee 分享返利
     * @apiSuccess {Boolean} recommend 是否在分销市场展示
     * @apiSuccess {Integer} totalCount 总记录数
     * @apiSuccess {Integer} totalPage 总页数
     * @apiSuccess {Integer} pageNo 页码
     * @apiSuccess {Integer} pageSize 每页记录数
     * @apiSuccessExample {json} Success-Response:
     * {
     *     "code":"1",
     *     "desc":"成功",
     *     "data":{
     *         "data":[
     *             {
     *                 "id":204,
     *                 "dateCreated":"2016-10-09 17:57:21",
     *                 "lastUpdated":"2016-10-10 11:27:39",
     *                 "version":5,
     *                 "identifier":"dd3dd9a4a63e8564c4a2ea984aa051ef",
     *                 "name":"bb",
     *                 "type":"GOODS",
     *                 "basePrice":442,
     *                 "sellPrice":445,
     *                 "quantity":1,
     *                 "carriage":0,
     *                 "refundable":false,
     *                 "sellnow":true,
     *                 "dateSelling":1476007041000,
     *                 "limitCount":0,
     *                 "logoUrl":"http://uploads.rockcent.com//dev/product/face/201610/9175713433d61a9b9c-0727-438b-8d29-d2ebef0e1f6bgithub-octocat_yes-we-code.jpg",
     *                 "logoUrls":"["http://uploads.rockcent.com//dev/product/face/201610/9175713433d61a9b9c-0727-438b-8d29-d2ebef0e1f6bgithub-octocat_yes-we-code.jpg"]",
     *                 "note":"2",
     *                 "status":"SELLING",
     *                 "mallId":1,
     *                 "merchantId":1,
     *                 "shippingType":"SHIPPING",
     *                 "resellFee":14,
     *                 "shareFee":0,
     *                 "recommend":false
     *             }
     *         ],
     *         "totalCount":225,
     *         "totalPage":45,
     *         "pageNo":0,
     *         "pageSize":5
     *     }
     * }
     *
     */
    @RequestMapping(value = Routes.PRODUCT_SEARCH, method = RequestMethod.GET)
    @ResponseBody
    public JsonResult search(String keyword, ProductDto productDto, HttpServletRequest request) {
        CustomerDto customerDto = customerHelper.getSession(request);
        RestDoing doing = jr -> {
            if (null == productDto.getPageNo() || null == productDto.getPageSize()) {
                jr.remind("请输入分页条件", log);
                return;
            }
            if ("saleCount".equalsIgnoreCase(productDto.getOrderBy())) {
                productDto.setOrderBy("saleCount");
                productDto.setSort("desc");
            } else {
                productDto.setOrderBy("sellPrice".equalsIgnoreCase(productDto.getOrderBy()) ? "sellPrice" : "ALL");
                productDto.setSort("asc".equalsIgnoreCase(productDto.getSort()) ? "asc" : "desc");
            }
            PageResult pageResult = new PageResult(productDto.getPageNo(), productDto.getPageSize());
            PageResult<Product> productList = merchantProductRepository.searchProduct(productDto, customerDto.getMallId(), ProductStatus.SELLING, keyword, pageResult);
            jr.setData(productList);
            //记录浏览数据
            ProductEventDto productEventDto = new ProductEventDto();
            productEventDto.setEventType(ProductEventType.VIEWED);
            productEventDto.setCustomerId(customerDto.getId());
            productEventDto.setCustomerName(customerDto.getNickName());
            productEventHelper.view(productList.data, productEventDto);
        };
        return doing.go(request, log);
    }

    /**
     * @api {get} /api/v2/product/evaluation/show_total 产品总体评价
     * @apiGroup product
     * @apiVersion 1.0.0
     * @apiParam {Long}productId 产品ID
     * @apiParam {Long}mallId 商城ID
     * @apiSuccess {Long} totalCommentSize 总评价数
     * @apiSuccess {Double} finalRangeStar 平均星数
     * @apiSuccess {String} rate 好评率
     * @apiSuccessExample {json} Success-Response:
     * {
     * "code": "1",
     * "desc": "成功",
     * "data": {
     * "totalCommentSize": 2,
     * "finalRangeStar": 3
     * "rate": "10%"
     * }
     */
    @RequestMapping(value = Routes.PRODUCT_EVALUATION_SHOW_TOTAL, method = RequestMethod.GET)
    @ResponseBody
    public JsonResult showTotalEvaluation(Long productId, HttpServletRequest request) {
        CustomerDto customerDto = customerHelper.getSession(request);
        RestDoing doing = jr -> {
            if (null == productId) {
                jr.errorParam("ProductID is null", log);
                return;
            }
            Product product = merchantProductRepository.findOne(productId);
            if (null == product) {
                jr.errorParam(Product.REMIND_RECORD_IS_NOT_EXIST, log);
                return;
            }
            //总评价
            Long totalCommentSize = evaluationRepository.countByProductId(productId);
            List<Evaluation> rangeStar = evaluationRepository.findByProductIdOrderByDateCreatedDesc(productId);
            EvaluationTotalDto evaluationTotalDto = new EvaluationTotalDto();
            //设置初值，评论数为0时，好评率为0；
            Double finalRangStar = 0D;
            String rate = "0%";

            //平均星数
            if (totalCommentSize > 0 && rangeStar != null) {
                finalRangStar = (rangeStar.stream().mapToDouble(param -> {
                    return param.getRangeStar();
                }).sum()) / totalCommentSize;

                //计算星数大于等于4的
                Long countRate = rangeStar.stream().filter(star -> star.getRangeStar() >= 4).count();
                //设置好评率
                NumberFormat numberFormat = NumberFormat.getPercentInstance();
                //整数最大3位
                numberFormat.setMaximumIntegerDigits(3);
                //小数最大0位
                numberFormat.setMaximumFractionDigits(0);
                rate = numberFormat.format(countRate / Double.valueOf(totalCommentSize));
            }
            evaluationTotalDto.setRate(rate);
            evaluationTotalDto.setTotalCommentSize(totalCommentSize);
            evaluationTotalDto.setFinalRangeStar(Math.ceil(finalRangStar));


            jr.setData(evaluationTotalDto);

        };
        return doing.go(request, log);
    }


    /**
     * @api {get} /api/v2/product/show_detail 查询图文详情
     * @apiGroup product
     * @apiVersion 1.0.0
     * @apiParam {Long} productId 产品ID
     * @apiParam {Long} mallId 商城ID
     * @apiSuccess {Long} id ID
     * @apiSuccess {Date} dateCreated 创建时间
     * @apiSuccess {Date} lastUpdated 更新时间
     * @apiSuccess {Long} version 版本
     * @apiSuccess {String} manual 购买须知
     * @apiSuccess {String} introduce 图文详情
     * @apiSuccess {Long} productId 产品ID
     * @apiSuccessExample {json} Success-Response:
     * {
     * "code": "1",
     * "desc": "成功",
     * "data": {
     * "id": 7,
     * "dateCreated": "2016-09-25 12:43:53",
     * "lastUpdated": "2016-09-25 12:43:54",
     * "version": 0,
     * "manual": "这个是测试的购买须知！",
     * "introduce": "<p>图文详情！！</p><p><img src=\"http://upload.dev.rockcent.com/images/20160506/20160506193523G6q90LZs.jpg\" title=\"20160506193523G6q90LZs.jpg\" alt=\"sy_64734564989.jpg\" imgtoken=\"15\"/></p><p><br/></p>",
     * "productId": 7
     * }
     */
    @RequestMapping(value = Routes.PRODUCT_SHOW_DETAIL, method = RequestMethod.GET)
    @ResponseBody
    public JsonResult showDetail(Long productId, HttpServletRequest request) {
        RestDoing doing = jr -> {
            if (null == productId) {
                jr.errorParam("ProductID is null", log);
                return;
            }
            Product product = merchantProductRepository.findByIdAndIsDeleteAndStatus(productId, Whether.NO, ProductStatus.SELLING);
            if (product == null) {
                jr.remind(ProductDetail.REMIND_RECORD_IS_NOT_EXIST, log);
                return;
            }
            Long targetId = productId;
            if (product.getMarketId() != null) {
                targetId = product.getMarketId();
            }
            ProductDetail productDetail = merchantProductDetailRepository.findByProductId(targetId);
            jr.setData(productDetail);
        };
        return doing.go(request, log);
    }

    /**
     * @api {post} /api/v2/product/evaluation/update 修改产品评价
     * @apiGroup product
     * @apiParam{String} mallId 商城ID
     * @apiParam{String} id 评价ID
     * @apiParam{String} productId 产品ID
     * @apiParam {String} customerId 客户Id
     * @apiParam {String} rangeStar 评级 1-5
     * @apiParam {String} comment 评价
     * @apiParam {String} commentCustomerName 评价人名称
     * @apiParam {Boolean} hideName 是否匿名 , false=不匿 true=匿名
     * @apiSuccess {Boolean} data 操作成功返回true
     * @apiSuccessExample {json} Success-Response:
     * {
     * "code": "1",
     * "desc": "成功",
     * "data": true
     * }
     */
    @RequestMapping(value = Routes.PRODUCT_EVALUATION_UPDATE, method = RequestMethod.POST)
    @ResponseBody
    public JsonResult updateEvaluation(Evaluation evaluation, Long mallId, HttpServletRequest request) {
        RestDoing doing = jr -> {
            if (null == mallId) {
                jr.remind("mallId:" + Mall.CHECK_ID_IS_NOT_NULL, log);
                return;
            }
            //判断mallid是否合法
            if (!mallRepository.exists(mallId)) {
                jr.remind(Mall.REMIND_RECORD_IS_NOT_EXIST, log);
                return;
            }
            //判空
            if (null == evaluation.getId()) {
                jr.remind("evaluationId:" + Evaluation.CHECK_ID_IS_NOT_NULL, log);
                return;
            }
            if (null == evaluation.getCustomerId()) {
                jr.remind("评价人不能为空", log);
                return;
            }
            if (null == evaluation.getProductId()) {
                jr.remind("商品不能为空", log);
                return;
            }
            //判断评论用户是否存在
            if (!customerRepository.exists(evaluation.getCustomerId())) {
                jr.errorParam(Customer.REMIND_RECORD_IS_NOT_EXIST, log);
                return;
            }
            //判断评论产品是否存在
            if (!merchantProductRepository.exists(evaluation.getProductId())) {
                jr.errorParam(Product.REMIND_RECORD_IS_NOT_EXIST, log);
                return;
            }
            Evaluation oldEvaluation = evaluationRepository.findOne(evaluation.getId());
            //判断新的评论用户是否原来的用户
            if (null == oldEvaluation || !oldEvaluation.getCustomerId().equals(evaluation.getCustomerId())) {
                jr.errorParam("非法操作", log);
                return;
            }
            //判断评论的产品是否原来的产品
            if (null == oldEvaluation || !oldEvaluation.getProductId().equals(evaluation.getProductId())) {
                jr.errorParam("非法操作", log);
                return;
            }
            //判断数据合法性
            if (null == evaluation.getRangeStar() || evaluation.getRangeStar() < 1 || evaluation.getRangeStar() > 5) {
                jr.errorParam("非法操作", log);
                return;
            }
            if (null == evaluation.getHideName()) {
                jr.errorParam("非法操作", log);
                return;
            }
            if (StringUtils.isBlank(evaluation.getCommentCustomerName())) {
                jr.remind("评价人不能为空", log);
                return;
            }

            oldEvaluation.setRangeStar(evaluation.getRangeStar());
            oldEvaluation.setHideName(evaluation.getHideName());
            oldEvaluation.setCommentCustomerName(evaluation.getHideName() ? "匿名" : evaluation.getCommentCustomerName());
            oldEvaluation.setComment(evaluation.getComment());

            Evaluation newEvaluation = evaluationRepository.save(oldEvaluation);
            if (null == newEvaluation) {
                jr.errorParam("操作不成功", log);
                return;
            }
            jr.setData(true);
        };
        return doing.go(request, log);
    }

    /**
     * @api {get} /api/v2/product/evaluation/list 产品评价列表
     * @apiGroup product
     * @apiParam{String} productId 产品ID
     * @apiParam{Boolean} customerSelf 是否用户自己的评价，true则查用户自己的评价
     * @apiSuccess {Long} id ID
     * @apiSuccess {Date} dateCreated 创建时间
     * @apiSuccess {Date} lastUpdated 更新时间
     * @apiSuccess {Long} version 版本
     * @apiSuccess {String} comment 评论
     * @apiSuccess {String} commentCustomerName 评论用户名
     * @apiSuccess {Long} customerId 评论用户ID
     * @apiSuccess {Long} merchantId 商户ID
     * @apiSuccess {Long} productId 产品ID
     * @apiSuccess {String} productName 产品名
     * @apiSuccess {Long} rangeStar 评价等级 1-5
     * @apiSuccess {Boolean} hideName 是否匿名
     * @apiSuccessExample {json} Success-Response:
     * {
     *     "code":"1",
     *     "desc":"成功",
     *     "data":[
     *         {
     *             "id":1,
     *             "dateCreated":"2016-06-20 16:18:18",
     *             "lastUpdated":"2016-06-20 16:18:18",
     *             "version":5,
     *             "comment":"WTF",
     *             "commentCustomerName":"匿名",
     *             "customerId":1,
     *             "headImgUrl":"http://uploads.rockcent.com//dev/product/face/201610/281356147194effef7-25bc-4938-b628-f5aa8c02835c211054917026928fca-75d6-43da-8f36-48399c2cd265giftPacketPromote.jpg",
     *             "merchantId":4,
     *             "productId":7,
     *             "productName":"自提-b2测试产品",
     *             "rangeStar":4,
     *             "hideName":true
     *         }
     *     ]
     * }
     *
     */
    @RequestMapping(value = Routes.PRODUCT_EVALUATION_LIST, method = RequestMethod.GET)
    @ResponseBody
    public JsonResult listEvaluation(Long productId, Boolean customerSelf, HttpServletRequest request) {
        CustomerDto customerDto = customerHelper.getSession(request);
        RestDoing doing = jr -> {
            if (null == productId) {
                jr.remind("productId:" + Product.CHECK_ID_IS_NOT_NULL, log);
                return;
            }
            //判断产品是否存在
            if (!merchantProductRepository.exists(productId)) {
                jr.remind(Product.REMIND_RECORD_IS_NOT_EXIST, log);
                return;
            }
            List<Evaluation> evaluationList = null;
            if (customerSelf != null && customerSelf) {
                evaluationList = evaluationRepository.findByproductIdAndCustomerIdOrderByDateCreatedDesc(productId, customerDto.getId());
            } else {
                evaluationList = evaluationRepository.findByProductIdOrderByDateCreatedDesc(productId);
            }
            List<EvaluationDto> evaluationDtoList = evaluationList.stream().map(evaluation -> {
                EvaluationDto evaluationDto = new EvaluationDto();
                RBeanUtils.copyProperties(evaluation, evaluationDto);
                Customer customer = customerRepository.findOne(evaluation.getCustomerId());
                evaluationDto.setHeadImgUrl(customer.getWechatHeadimgurl());
                return evaluationDto;
            }).collect(Collectors.toList());
            jr.setData(evaluationDtoList);

        };
        return doing.go(request, log);
    }

    /**
     * @api {get} /api/v2/product/discovery 发现产品
     * @apiGroup product
     * @apiParam {String} mallId 商城ID
     * @apiParam {String} longitude 经度
     * @apiParam {String} latitude 纬度
     * @apiSuccess {Long} id ID
     * @apiSuccess {Date} dateCreated 创建时间
     * @apiSuccess {Date} lastUpdated 更新时间
     * @apiSuccess {String} version 版本号
     * @apiSuccess {String} name 名称
     * @apiSuccess {String} type 类型 ALL("全部"), GOODS("商品"), SERVICE("服务")
     * @apiSuccess {BigDecimal} basePrice 原价
     * @apiSuccess {BigDecimal} sellPrice 售价
     * @apiSuccess {Long} quantity  库存数量
     * @apiSuccess {BigDecimal} carriage 运费
     * @apiSuccess {Date} dateEnabled
     * @apiSuccess {Date} dateDisabled
     * @apiSuccess {Boolean} refundable 是否支持过期退
     * @apiSuccess {Boolean} sellnow 是否立即开售
     * @apiSuccess {Date} dateSelling 开售时间
     * @apiSuccess {Long} limitCount 限购数量
     * @apiSuccess {String} logoUrl LOGO图
     * @apiSuccess {String} note 卖点介绍
     * @apiSuccess {String} status 状态 SELLING("在售"), SUPPLIER_CANCEL_SOLDOUT("分销市场 供应商取消供货 已下架"),DISTRIBUTOR_CANCEL_SOLDOUT("分销市场 分销商取消代销 已下架"), SOLDOUT("已下架"), EXPIRED("已过期"), DELETED("已删除"), WAIT_APPLY("待申请"), WAIT_AUDIT("待审核"), AUDIT_PASS("审核通过"), AUDIT_FAIL("审核不通过")
     * @apiSuccess {Long} mallId 平台ID
     * @apiSuccess {Long} merchantId 商家ID
     * @apiSuccess {String} serveRate 服务费比率
     * @apiSuccess {String} shippingType 支持的物流类型 SHOP_PICKUP("到店自取"), SHIPPING("物流"), SHOP_PICKUP_AND_SHIPPING("物流及到店自取")
     * @apiSuccess {BigDecimal} resellFee 分销佣金
     * @apiSuccess {BigDecimal} shareFee 分享返利
     * @apiSuccess {Boolean} recommend 是否在分销市场展示
     * @qpiSuccess {String} marketPlatformType 分销类型 IN_PLATFORM("平台内"), OUT_PLATFORM("平台外")
     * @apiSuccess {String} promoteUrl 产品推广二维码图片路径
     * @apiSuccessExample {json} Success-Response:
     *{
     *    "code":"1",
     *    "desc":"成功",
     *    "data":[
     *        {
     *            "id":85,
     *            "dateCreated":"2016-06-07 18:09:37",
     *            "lastUpdated":"2016-10-14 14:09:52",
     *            "version":5,
     *            "name":"测试BDC不可退！",
     *            "type":"SERVICE",
     *            "basePrice":100,
     *            "sellPrice":99,
     *            "quantity":1000,
     *            "carriage":0,
     *            "dateEnabled":"2016-05-13 00:00:00",
     *            "dateDisabled":"2017-05-13 00:00:00",
     *            "refundable":false,
     *            "sellnow":true,
     *            "dateSelling":"2016-06-07 18:09:37",
     *            "limitCount":0,
     *            "logoUrl":"http://upload.dev.rockcent.com/images/20160513/20160513180613J2f5pAK6.jpg",
     *            "note":"卖点介绍",
     *            "status":"SELLING",
     *            "mallId":1,
     *            "merchantId":1,
     *            "serveRate":"0",
     *            "shippingType":"SHIPPING",
     *            "resellFee":4,
     *            "shareFee":0,
     *            "marketPlatformType":"OUT_PLATFORM",
     *            "promoteUrl":"http://uploads.rockcent.com/dev/product/promote/201610/91447423299a63c319-e200-4d45-bf9c-3de0dd1785dapromote.jpg"
     *        }
     *    ]
     *
     *
     */
    @RequestMapping(value = Routes.PRODUCT_DISCOVERY, method = RequestMethod.GET)
    @ResponseBody
    public JsonResult discovery(String longitude, String latitude, HttpServletRequest request) {
        CustomerDto customerDto = customerHelper.getSession(request);
        RestDoing doing = jr -> {

            if (StringUtils.isBlank(longitude) || StringUtils.isBlank(latitude)) {
                jr.remind("longitude 和 latitude 不能为空", log);
                return;
            }
//            log.info("======================>经纬记录：" + longitude + "," + latitude);
            List<Product> productList = merchantProductRepository.findByMallIdAndStatusAndMarketIdIsNullAndDateSellingBeforeOrderByLastUpdatedDesc(customerDto.getMallId(), ProductStatus.SELLING, new Date());

            productList.stream().map(product -> {
                ProductEvent productEvent = new ProductEvent();
                productEvent.setMallId(product.getMallId());
                productEvent.setMerchantId(product.getMerchantId());
                productEvent.setProductId(product.getId());
                productEvent.setEventType(ProductEventType.VIEWED);
                productEvent.setNum(1);
                productEvent.setPrice(product.getSellPrice());
                productEvent.setTotalPrice(product.getSellPrice());
                productEvent.setProductType(product.getType().toString());
                productEvent.setProductName(product.getName());

                productEventRepository.save(productEvent);
                return null;
            });
            //记录用户浏览痕迹
            ProductEventDto productEventDto = new ProductEventDto();
            productEventDto.setEventType(ProductEventType.VIEWED);
            productEventDto.setCustomerId(customerDto.getId());
            productEventDto.setCustomerName(customerDto.getNickName());
            productEventHelper.view(productList, productEventDto);

            jr.setData(productList);
        };
        return doing.go(request, log);
    }

    /**
     * @api {post} /api/v2/product/evaluation/add 增加产品评价
     * @apiGroup product
     * @apiParam {String} productId 产品ID
     * @apiParam {String} rangeStar 评级 1-5
     * @apiParam {String} [comment] 评价
     * @apiParam {String} isHideName 是否匿名 , false=不匿 true=匿名
     * @apiParam {Long} merchantOrderId <code>必传参数</code>订单ID
     * @apiParamExample {json} 评价传参格式:
     * {
     *     "merchantOrderId":4137,
     *     "evaluationList":[
     *         {
     *             "comment":"WTF012",
     *             "productId":1056,
     *             "rangeStar":4,
     *             "isHideName":true
     *         },
     *         {
     *             "comment":"WTF012",
     *             "productId":1056,
     *             "rangeStar":4,
     *             "isHideName":true
     *         }
     *     ]
     * }
     *
     * @apiSuccessExample {json} Success-Response:
     * {
     *  "code": "1",
     *  "desc": "成功",
     *  "data": true
     * }
     */
    @Transactional
    @RequestMapping(value = Routes.PRODUCT_EVALUATION_ADD, method = RequestMethod.POST)
    public JsonResult addEvaluation(@RequestBody EvaluationDto evaluationDto, HttpServletRequest request) {
        CustomerDto customerDto = customerHelper.getSession(request);
        RestDoing doing = jr -> {
            MerchantOrder merchantOrder = merchantOrderRepository.findOne(evaluationDto.getMerchantOrderId());
            if (merchantOrder == null || merchantOrder.getEvaluateStatus() == EvaluateStatus.HAD_EVALUATE) {
                jr.errorParam("订单不存在或已经评价了", log);
                return;
            }
            List<MerchantOrderItem> merchantOrderItemList = merchantOrderItemRepository.findByMerchantOrderId(evaluationDto.getMerchantOrderId());
            List<Long> productIdList = merchantOrderItemList.stream().map(MerchantOrderItem::getProductId).collect(Collectors.toList());
            if (productIdList == null || productIdList.size() == 0) {
                jr.errorParam("订单错误", log);
                return;
            }

            if (evaluationDto.getEvaluationList() == null || evaluationDto.getEvaluationList().size() == 0) {
                jr.errorParam("评价产品集合 不能为空", log);
                return;
            }

            //数据校验
            Boolean flag = evaluationDto.getEvaluationList().stream().allMatch(evaluation -> {
                Boolean innerFlag = true;
                if (null == evaluation.getProductId()) {
                    jr.remind("productId:" + Mall.CHECK_ID_IS_NOT_NULL, log);
                    innerFlag = false;
                }
                if (null == evaluation.getRangeStar() || evaluation.getRangeStar() < 1 || evaluation.getRangeStar() > 5) {
                    jr.errorParam("rangeStar:" + evaluation.getRangeStar() + "，只能大于等于1，小于等于5", log);
                    innerFlag = false;
                }
                if (null == evaluation.getHideName()) {
                    jr.errorParam("hideName:" + evaluation.getHideName() + ",需要true或false", log);
                    innerFlag = false;
                }
                //检查评价产品是否订单产品
                if (!productIdList.contains(evaluation.getProductId())) {
                    jr.errorParam("产品" + evaluation.getProductId() + "不存在", log);
                    innerFlag = false;
                }
                return innerFlag;
            });
            if (!flag) {
                return;
            }
            Long customerDtoId = customerDto.getId();
            productSrv.addEv(customerDtoId, evaluationDto, merchantOrder);
            jr.setData(true);
        };
        return doing.go(request, log);
    }

    /**
     * @api {get} /api/v2/product/list 查询产品列表
     * @apiGroup product
     * @apiParam {Long} [categoryId] 分类ID
     * @apiParam {Long} [merchantId] 商家ID
     * @apiParam {String} orderBy <code>必传参数</code>排序字段 : 按sellPrice(售价排序)，ALL(默认综合排序，按设定好的规则排)，saleCount（按销量降序）
     * @apiParam {String} sort <code>必传参数</code>升序 asc , 降序 desc，不管哪种排序，该字段必须传
     * @apiSuccess {Long} id ID
     * @apiSuccess {Date} dateCreated 创建时间
     * @apiSuccess {Date} lastUpdated 更新时间
     * @apiSuccess {String} name 名称
     * @apiSuccess {String} type 类型 ALL("全部"), GOODS("商品"), SERVICE("服务")
     * @apiSuccess {BigDecimal} basePrice 原价
     * @apiSuccess {BigDecimal} sellPrice 售价
     * @apiSuccess {Long} quantity  库存数量
     * @apiSuccess {BigDecimal} carriage 运费
     * @apiSuccess {Boolean} refundable 是否支持过期退
     * @apiSuccess {Boolean} sellnow 是否立即开售
     * @apiSuccess {Date} dateSelling 开售时间
     * @apiSuccess {Long} limitCount 限购数量
     * @apiSuccess {String} logoUrl LOGO图
     * @apiSuccess {String} note 卖点介绍
     * @apiSuccess {String} status 状态 SELLING("在售"), SUPPLIER_CANCEL_SOLDOUT("分销市场 供应商取消供货 已下架"),DISTRIBUTOR_CANCEL_SOLDOUT("分销市场 分销商取消代销 已下架"), SOLDOUT("已下架"), EXPIRED("已过期"), DELETED("已删除"), WAIT_APPLY("待申请"), WAIT_AUDIT("待审核"), AUDIT_PASS("审核通过"), AUDIT_FAIL("审核不通过")
     * @apiSuccess {Long} mallId 平台ID
     * @apiSuccess {Long} merchantId 商家ID
     * @apiSuccess {String} serveRate 服务费比率
     * @apiSuccess {String} shippingType 支持的物流类型 SHOP_PICKUP("到店自取"), SHIPPING("物流"), SHOP_PICKUP_AND_SHIPPING("物流及到店自取")
     * @apiSuccess {BigDecimal} resellFee 分销佣金
     * @apiSuccess {BigDecimal} shareFee 分享返利
     * @apiSuccess {Boolean} recommend 是否在分销市场展示
     * @apiSuccessExample {json} Success-Response:
     * {
     *     "code":"1",
     *     "desc":"成功",
     *     "data":{
     *         "data":[
     *             {
     *                 "id":82,
     *                 "dateCreated":"2016-10-10 16:51:14",
     *                 "lastUpdated":"2016-10-10 16:51:15",
     *                 "name":"223",
     *                 "type":"GOODS",
     *                 "basePrice":22,
     *                 "sellPrice":11,
     *                 "quantity":9,
     *                 "carriage":0,
     *                 "refundable":false,
     *                 "sellnow":true,
     *                 "dateSelling":1465204331000,
     *                 "limitCount":0,
     *                 "logoUrl":"/20160606/20160606171158cHxUwq5b.png",
     *                 "note":"11",
     *                 "status":"SELLING",
     *                 "mallId":1,
     *                 "merchantId":1,
     *                 "serveRate":"24",
     *                 "shippingType":"SHIPPING",
     *                 "resellFee":1,
     *                 "shareFee":0,
     *                 "recommend":false
     *             }
     *         ]
     *     }
     * }
     *
     */
    @RequestMapping(value = Routes.PRODUCT_LIST, method = RequestMethod.GET)
    @ResponseBody
    public JsonResult list(Long categoryId, ProductDto productDto, HttpServletRequest request) {
        CustomerDto customerDto = customerHelper.getSession(request);
        RestDoing doing = jr -> {

            if (null == productDto.getPageNo() || null == productDto.getPageSize()) {
                jr.remind("请输入分页条件", log);
                return;
            }
            if (StringUtils.isBlank(productDto.getOrderBy()) || StringUtils.isBlank(productDto.getSort())) {
                jr.remind("请正确输入排序条件", log);
                return;
            }

            List<Long> productIdList = null;
            if (categoryId != null) {
                List<ProductCategories> productCategories = merchantProductCategoriesRepository.findByCategoryIdAndIsDelete(categoryId, Whether.NO);
                productIdList = productCategories.stream().map(ProductCategories::getProductId).collect(Collectors.toList());
                if (productIdList == null || productIdList.size() == 0) {
                    jr.remind("此类目下没有产品", log);
                    return;
                }
            }

            if ("saleCount".equalsIgnoreCase(productDto.getOrderBy())) {
                productDto.setOrderBy("saleCount");
                productDto.setSort("desc");
            } else {
                productDto.setOrderBy("sellPrice".equalsIgnoreCase(productDto.getOrderBy()) ? "sellPrice" : "ALL");
                productDto.setSort("asc".equalsIgnoreCase(productDto.getSort()) ? "asc" : "desc");
            }

            //默认按销量排序，要传顺序sort
            PageResult<Product> productPage = merchantProductRepository.getProductListToMem(productIdList, customerDto.getMallId(), productDto.getMerchantId(), productDto, this.getPage(productDto.getPageNo(), productDto.getPageSize()));
            jr.setData(productPage);
            //记录用户浏览痕迹
            ProductEventDto productEventDto = new ProductEventDto();
            productEventDto.setEventType(ProductEventType.VIEWED);
            productEventDto.setCustomerId(customerDto.getId());
            productEventDto.setCustomerName(customerDto.getNickName());
            productEventHelper.view(productPage.data, productEventDto);
        };
        return doing.go(request, log);
    }

   /* *//**
     * @api{get} /api/v2/product/store/list 产品适用门店列表
     * @apiGroup product
     * @apiParam {String} merchantId 商铺ID
     * @apiParam {Long} productID 产品id
     *
     * @apiSuccess {String} locationStr 区域
     * @apiSuccess {String} address 街道地址
     * @apiSuccess {String} third 地址
     * @apiSuccess {String} phone 联系电话
     * @apiSuccess {String} name 门店名
     * @apiSuccess {String} exchange 可否兑换
     * @apiSuccess {String} type 门店类型
     * @apiSuccessExample {json} Success-Response:
     * HTTP/1.1 200 OK
     *  {
     *      "code": 1,
     *      "desc": "成功",
     *      "data":{
     *          "data": [
     *              {
     *                  "locationStr" : "广东省从化市",
     *                  "address": "江埔街凤院村源龙队68号",
     *                  "third": "https://www.baidu.com/",
     *                  "phone": "15920385185,15920385186,",
     *                  "name": "xxxx门店1",
     *                  "exchange": "YES",
     *                  "id": 1,
     *                  "type": "STORE"
     *              }
     *          ]
     *      }
     *  }
     *//*
    @RequestMapping(value = Routes.PRODUCT_STORE_LIST, method = RequestMethod.GET)
    @ResponseBody
    public JsonResult productStoreList(HttpServletRequest request, Long productId, Long merchantId) {
        RestDoing doing = jr -> {
            Product product = merchantProductRepository.findByIdAndMerchantIdAndIsDelete(productId, merchantId, Whether.NO);
            if (null == product) {
                jr.remind(Product.REMIND_RECORD_IS_NOT_EXIST,log);
                return;
            }
            if (ProductType.SERVICE == product.getType() || ProductShippingType.SHOP_PICKUP == product.getShippingType()) {
                List<MerchantStore> merchantStoreList = new ArrayList<>();
                if (ProductMerchantStoreType.ALL == product.getProductMerchantStoreType()) {
                    merchantStoreList = merchantStoreRepository.findByMerchantIdAndExchangeAndStatusAndIsDelete(merchantId, Whether.YES, MerchantStoreStatus.ENABLE, Whether.NO);
                } else if (ProductMerchantStoreType.PART == product.getProductMerchantStoreType()) {
                    merchantStoreList = merchantStoreRepository.findProductStoreList(productId, merchantId);
                }
                jr.setData(merchantStoreList);
            }
        };
        return doing.go(request, log);
    }*/

    /**
     * @api {get} /api/v2/product/info/{id} 查询产品详情
     * @apiGroup product
     * @apiParam {Long} id 产品ID
     * @apiSuccess {Long} id 产品ID
     * @apiSuccess {Date} dateCreated 创建时间
     * @apiSuccess {Date} lastUpdated 更新时间
     * @apiSuccess {String} name 名称
     * @apiSuccess {BigDecimal} basePrice 原价
     * @apiSuccess {BigDecimal} sellPrice 售价
     * @apiSuccess {Long} quantity  库存数量
     * @apiSuccess {Boolean} refundable 是否支持过期退
     * @apiSuccess {Boolean} sellnow 是否立即开售
     * @apiSuccess {Date} dateSelling 开售时间
     * @apiSuccess {Long} limitCount 限购数量
     * @apiSuccess {String} logoUrl LOGO图
     * @apiSuccess {String} logoUrls 多LOGO图
     * @apiSuccess {String} note 卖点介绍
     * @apiSuccess {String} status 状态 SELLING("在售"), SUPPLIER_CANCEL_SOLDOUT("分销市场 供应商取消供货 已下架"),DISTRIBUTOR_CANCEL_SOLDOUT("分销市场 分销商取消代销 已下架"), SOLDOUT("已下架"), EXPIRED("已过期"), DELETED("已删除"), WAIT_APPLY("待申请"), WAIT_AUDIT("待审核"), AUDIT_PASS("审核通过"), AUDIT_FAIL("审核不通过")
     * @apiSuccess {Long} mallId 平台ID
     * @apiSuccess {Long} merchantId 商家ID
     * @apiSuccess {String} serveRate 服务费比率
     * @apiSuccess {String} shippingType 支持的物流类型 SHOP_PICKUP("到店自取"), SHIPPING("物流"), SHOP_PICKUP_AND_SHIPPING("物流及到店自取")
     * @apiSuccess {BigDecimal} resellFee 分销佣金
     * @apiSuccess {BigDecimal} shareFee 分享返利
     * @apiSuccess {String} favourite 是否已收藏，YES:已收藏，NO:未收藏
     * @apiSuccess {String} imgUrl 商家logo
     * @apiSuccessExample {json} Success-Response:
     * {
     *     "code":"1",
     *     "desc":"成功",
     *     "data":{
     *         "id":11,
     *         "dateCreated":"2016-05-09 12:06:00",
     *         "lastUpdated":"2016-10-21 16:47:39",
     *         "name":"自提-B1测试自提",
     *         "basePrice":100,
     *         "sellPrice":0.01,
     *         "quantity":1000,
     *         "refundable":false,
     *         "barcode":"mmm19234",
     *         "sellnow":true,
     *         "dateSelling":"2016-05-09 12:05:35",
     *         "limitCount":0,
     *         "logoUrl":"/20160509/20160509120510Fy0WSvJL.jpg",
     *         "logoUrls":[
     *             "["http://uploads.rockcent.com//dev/product/face/201610/111947789235c7738e-f4f1-4349-9319-a4257f85e710github-octocat_yes-we-code.jpg"",
     *             ""http://uploads.rockcent.com//dev/product/face/201610/11194710634de271b8a-54c7-4b5e-b0fe-7afd020da751Evangelion_My-Little-Pony_1.jpg"]"
     *         ],
     *         "note":"卖点介绍",
     *         "mallId":1,
     *         "merchantId":1,
     *         "serveRate":"2.5",
     *         "shippingType":"SHOP_PICKUP_AND_SHIPPING",
     *         "shareFee":0,
     *         "merchantName":"asd",
     *         "favourite":"YES",
     *         "imgUrl":"http://uploads.rockcent.com//dev/merchant/logo/201610/131336332032d675e6f-482e-4a2f-8e65-40a42f840110Tulips.jpg"
     *     }
     * }
     */
    @RequestMapping(value = Routes.PRODUCT_INFO, method = RequestMethod.GET)
    @ResponseBody
    public JsonResult show(@PathVariable Long id, HttpServletRequest request) {
        CustomerDto customerDto = customerHelper.getSession(request);
        RestDoing doing = jr -> {
            if (null == id) {
                jr.remind(Product.CHECK_ID_IS_NOT_NULL, log);
                return;
            }

            Product product = merchantProductRepository.findByIdAndIsDelete(id, Whether.NO);
            if (null == product) {
                jr.remind(Product.REMIND_RECORD_IS_NOT_EXIST, log);
                return;
            }

            ProductDto productDto = new ProductDto();
            RBeanUtils.copyProperties(product, productDto);
            productDto.setType(product.getType().toString());
            productDto.setStatus(String.valueOf(product.getStatus()));
            productDto.setSellPrice(product.getSellPrice().doubleValue());
            Double basePrice = null == product.getBasePrice() ? null : product.getBasePrice().doubleValue();
            productDto.setBasePrice(basePrice);
            productDto.setLogoUrls(new ArrayList<>());
            if (product.getLogoUrls() != null) {
                String logoUrls = product.getLogoUrls();
                productDto.setLogoUrls(objectMapper.readValue(product.getLogoUrls(), new TypeReference<List<String>>() {
                }));
            }
            productDto.setShareFee(product.getShareFee().doubleValue());

            if (customerDto != null) {
                Favorite favorite = favoriteRepository.findByCustomerIdAndProductIdAndType(customerDto.getId(), id, FavoriteType.PRODUCT);
                if (favorite != null) {
                    productDto.setFavourite(Whether.YES);
                }
            }
            //库存
            ProductQuantity productQuantity = productQuantityRepository.findById(product.getProductQuantityId());
            productDto.setQuantity(productQuantity.getQuantity());

            Merchant merchant = merchantRepository.findOne(product.getMerchantId());
            //防止商家已删除报错
            if (merchant != null) {
                productDto.setImgUrl(merchant.getLogoUrl());
                productDto.setSalesCode(merchant.getSalesCode());
                productDto.setMerchantName(merchant.getName());
            }
            productDto.setShippingType(product.getShippingType().toString());
//            将统计数据删除
//            //记录浏览记录
//            //渠道信息
//            String finalChanelId = channelId;
//            if (StringUtils.isBlank(finalChanelId)) {
//                Channel channel = channelRepository.findByMerchantIdAndName(product.getMerchantId(), Channel.DEFAULT_SELF_CHANNEL_NAME);
//                if (channel != null) {
//                    finalChanelId = channel.getId().toString();
//                }
//            }
//            ProductEventDto productEventDto = new ProductEventDto(product,customerDto.getId(),ProductEventType.CLICKED);
//            productEventDto.setChannelId(finalChanelId);
//            productEventDto.setShareCode(shareCode);
//            productEventDto.setSalesCode(salesCode);
//            productEventDto.setCustomerName(customerDto.getNickName());
//            productEventHelper.productEventRecord(productEventDto);

            jr.setData(productDto);
        };
        return doing.go(request, log);
    }

    /**
     * @api {get} /api/v2/product/show/{id} 查询产品详情
     * @apiGroup product
     * @apiParam {Long} mallId 商城ID
     * @apiParam {Long} productId 产品ID
     * @apiParam {String} [channelId] 渠道ID
     * @apiParam {String} [shareCode] 分享码
     * @apiParam {String} [salesCode] 分销码
     * @apiSuccess {Long} id 产品ID
     * @apiSuccess {Date} dateCreated 创建时间
     * @apiSuccess {Date} lastUpdated 更新时间
     * @apiSuccess {String} name 名称
     * @apiSuccess {BigDecimal} basePrice 原价
     * @apiSuccess {BigDecimal} sellPrice 售价
     * @apiSuccess {BigDecimal} friendPrice 朋友价
     * @apiSuccess {Long} quantity  库存数量
     * @apiSuccess {Boolean} refundable 是否支持过期退
     * @apiSuccess {Boolean} sellnow 是否立即开售
     * @apiSuccess {Date} dateSelling 开售时间
     * @apiSuccess {Long} limitCount 限购数量
     * @apiSuccess {String} logoUrl LOGO图
     * @apiSuccess {String} logoUrls 多LOGO图
     * @apiSuccess {String} note 卖点介绍
     * @apiSuccess {String} status 状态 SELLING("在售"), SUPPLIER_CANCEL_SOLDOUT("分销市场 供应商取消供货 已下架"),DISTRIBUTOR_CANCEL_SOLDOUT("分销市场 分销商取消代销 已下架"), SOLDOUT("已下架"), EXPIRED("已过期"), DELETED("已删除"), WAIT_APPLY("待申请"), WAIT_AUDIT("待审核"), AUDIT_PASS("审核通过"), AUDIT_FAIL("审核不通过")
     * @apiSuccess {Long} mallId 平台ID
     * @apiSuccess {Long} merchantId 商家ID
     * @apiSuccess {String} serveRate 服务费比率
     * @apiSuccess {String} shippingType 支持的物流类型 SHOP_PICKUP("到店自取"), SHIPPING("物流"), SHOP_PICKUP_AND_SHIPPING("物流及到店自取")
     * @apiSuccess {BigDecimal} resellFee 分销佣金
     * @apiSuccess {BigDecimal} shareFee 分享返利
     * @apiSuccess {String} favourite 是否已收藏，YES:已收藏，NO:未收藏
     * @apiSuccess {String} imgUrl 商家logo
     * @apiSuccessExample {json} Success-Response:
     * {
     *     "code":"1",
     *     "desc":"成功",
     *     "data":{
     *         "id":11,
     *         "dateCreated":"2016-05-09 12:06:00",
     *         "lastUpdated":"2016-10-21 16:47:39",
     *         "name":"自提-B1测试自提",
     *         "basePrice":100,
     *         "sellPrice":0.01,
     *         "quantity":1000,
     *         "refundable":false,
     *         "barcode":"mmm19234",
     *         "sellnow":true,
     *         "dateSelling":"2016-05-09 12:05:35",
     *         "limitCount":0,
     *         "logoUrl":"/20160509/20160509120510Fy0WSvJL.jpg",
     *         "logoUrls":[
     *             "["http://uploads.rockcent.com//dev/product/face/201610/111947789235c7738e-f4f1-4349-9319-a4257f85e710github-octocat_yes-we-code.jpg"",
     *             ""http://uploads.rockcent.com//dev/product/face/201610/11194710634de271b8a-54c7-4b5e-b0fe-7afd020da751Evangelion_My-Little-Pony_1.jpg"]"
     *         ],
     *         "note":"卖点介绍",
     *         "mallId":1,
     *         "merchantId":1,
     *         "serveRate":"2.5",
     *         "shippingType":"SHOP_PICKUP_AND_SHIPPING",
     *         "shareFee":0,
     *         "merchantName":"asd",
     *         "favourite":"YES",
     *         "imgUrl":"http://uploads.rockcent.com//dev/merchant/logo/201610/131336332032d675e6f-482e-4a2f-8e65-40a42f840110Tulips.jpg"
     *     }
     * }
     */
    @RequestMapping(value = Routes.PRODUCT_SHOW, method = RequestMethod.GET)
    @ResponseBody
    public JsonResult show(@PathVariable Long id, String shareCode, String salesCode, String channelId, HttpServletRequest request) {
        CustomerDto customerDto = customerHelper.getSession(request);
        RestDoing doing = jr -> {
            if (null == id) {
                jr.remind(Product.CHECK_ID_IS_NOT_NULL, log);
                return;
            }

            Product product = merchantProductRepository.findByIdAndIsDelete(id, Whether.NO);
            if (null == product) {
                jr.remind(Product.REMIND_RECORD_IS_NOT_EXIST, log);
                return;
            }

            ProductDto productDto = new ProductDto();
            RBeanUtils.copyProperties(product, productDto);
            productDto.setType(product.getType().toString());
            productDto.setStatus(String.valueOf(product.getStatus()));
            productDto.setSellPrice(product.getSellPrice().doubleValue());
            Double basePrice = null == product.getBasePrice() ? null : product.getBasePrice().doubleValue();
            productDto.setBasePrice(basePrice);

            productDto.setLogoUrls(new ArrayList<>());
            if (product.getLogoUrls() != null) {
                String logoUrls = product.getLogoUrls();
                productDto.setLogoUrls(objectMapper.readValue(product.getLogoUrls(), new TypeReference<List<String>>() {
                }));
            }
            productDto.setShareFee(product.getShareFee().doubleValue());

            if (customerDto != null) {
                Favorite favorite = favoriteRepository.findByCustomerIdAndProductIdAndType(customerDto.getId(), id, FavoriteType.PRODUCT);
                if (favorite != null) {
                    productDto.setFavourite(Whether.YES);
                }
            }
            //库存
            ProductQuantity productQuantity = productQuantityRepository.findById(product.getProductQuantityId());
            productDto.setQuantity(productQuantity.getQuantity());
            Merchant merchant = merchantRepository.findOne(product.getMerchantId());
            //防止商家被删除报错
            if (merchant != null) {
                productDto.setImgUrl(merchant.getLogoUrl());
                productDto.setSalesCode(merchant.getSalesCode());
                productDto.setMerchantName(merchant.getName());
            }
            productDto.setShippingType(product.getShippingType().toString());

            //朋友价
            MallFinancialSettings mallFinancialSettings = mallFinancialSettingsRepository.findTop1ByMallIdAndIsDeleteOrderByLastUpdatedDesc(customerDto.getMallId(), Whether.NO);
            BigDecimal shareRate = mallFinancialSettings.getShareFeeRate() == null ? BigDecimal.valueOf(0) : mallFinancialSettings.getShareFeeRate();
            BigDecimal shareFeeRates = BigDecimalUtils.divide(BigDecimal.valueOf(100 - shareRate.doubleValue()), "100");
            productDto.setFriendPrice(productDto.getSellPrice() - new BigDecimal(productDto.getShareFee()).multiply(shareFeeRates).doubleValue());

            //记录浏览记录
            //渠道信息
            String finalChanelId = channelId;
            if (StringUtils.isBlank(finalChanelId)) {
                Channel channel = channelRepository.findByMerchantIdAndName(product.getMerchantId(), Channel.DEFAULT_SELF_CHANNEL_NAME);
                if (channel != null) {
                    finalChanelId = channel.getId().toString();
                }
            }
            ProductEventDto productEventDto = new ProductEventDto(product, customerDto.getId(), ProductEventType.CLICKED);
            productEventDto.setChannelId(finalChanelId);
            productEventDto.setShareCode(shareCode);
            productEventDto.setSalesCode(salesCode);
            productEventDto.setCustomerName(customerDto.getNickName());
            productEventHelper.productEventRecord(productEventDto);

            jr.setData(productDto);
        };
        return doing.go(request, log);
    }


    /**
     * @api {get} /api/v2/product/coupon_list 票券适用的产品
     * @apiGroup product
     * @apiParam {Long} couponId 票券ID
     * @apiParam {Long} pageNo 页
     * @apiParam {Long} pageSize 页记录数
     * @apiSuccess {Long} id 产品ID
     * @apiSuccess {Date} dateCreated 创建时间
     * @apiSuccess {Date} lastUpdated 更新时间
     * @apiSuccess {String} name 名称
     * @apiSuccess {BigDecimal} basePrice 原价
     * @apiSuccess {BigDecimal} sellPrice 售价
     * @apiSuccess {Long} quantity  库存数量
     * @apiSuccess {Boolean} refundable 是否支持过期退
     * @apiSuccess {Boolean} sellnow 是否立即开售
     * @apiSuccess {Date} dateSelling 开售时间
     * @apiSuccess {Long} limitCount 限购数量
     * @apiSuccess {String} logoUrl LOGO图
     * @apiSuccess {String} logoUrls 多LOGO图
     * @apiSuccess {String} note 卖点介绍
     * @apiSuccess {String} status 状态 SELLING("在售"), SUPPLIER_CANCEL_SOLDOUT("分销市场 供应商取消供货 已下架"),DISTRIBUTOR_CANCEL_SOLDOUT("分销市场 分销商取消代销 已下架"), SOLDOUT("已下架"), EXPIRED("已过期"), DELETED("已删除"), WAIT_APPLY("待申请"), WAIT_AUDIT("待审核"), AUDIT_PASS("审核通过"), AUDIT_FAIL("审核不通过")
     * @apiSuccess {Long} mallId 平台ID
     * @apiSuccess {Long} merchantId 商家ID
     * @apiSuccess {String} serveRate 服务费比率
     * @apiSuccess {String} shippingType 支持的物流类型 SHOP_PICKUP("到店自取"), SHIPPING("物流"), SHOP_PICKUP_AND_SHIPPING("物流及到店自取")
     * @apiSuccess {BigDecimal} resellFee 分销佣金
     * @apiSuccess {BigDecimal} shareFee 分享返利
     * @apiSuccess {Integer} totalCount 总记录数
     * @apiSuccess {Integer} totalPage 总页数
     * @apiSuccess {Integer} pageNo 页码
     * @apiSuccess {Integer} pageSize 每页记录数
     * @apiSuccessExample {json} Success-Response:
     * {
     *     "code":"1",
     *     "desc":"成功",
     *     "data":{
     *         "data":[
     *             {
     *                 "id":71,
     *                 "dateCreated":"2016-06-01 14:13:43",
     *                 "lastUpdated":"2016-10-21 15:50:09",
     *                 "version":4,
     *                 "name":"宇宙",
     *                 "type":"GOODS",
     *                 "basePrice":110,
     *                 "sellPrice":100,
     *                 "quantity":998,
     *                 "carriage":0,
     *                 "refundable":false,
     *                 "sellnow":true,
     *                 "dateSelling":"2016-06-01 14:13:43",
     *                 "limitCount":0,
     *                 "logoUrl":"/20160601/201606011413084VOvLKgN.jpg",
     *                 "note":"全宇宙最漂亮的",
     *                 "status":"SELLING",
     *                 "mallId":1,
     *                 "merchantId":1,
     *                 "serveRate":"24",
     *                 "resellFee":5,
     *                 "shareFee":2,
     *                 "recommend":false
     *             }
     *         ],
     *         "totalCount":3,
     *         "totalPage":1,
     *         "pageNo":0,
     *         "pageSize":10
     *     }
     * }
     *
     */
    @RequestMapping(value = Routes.PRODCUT_COUPON_LIST, method = RequestMethod.GET)
    @ResponseBody
    public JsonResult couponList(ProductDto productDto, Long couponId, HttpServletRequest request) {
        CustomerDto customerDto = customerHelper.getSession(request);
        RestDoing doing = jr -> {
            if (null == productDto.getPageNo() || null == productDto.getPageSize()) {
                jr.remind("请输入分页条件", log);
                return;
            }
            if (couponId == null) {
                jr.remind("couponId is null", log);
                return;
            }
            MerchantCoupon coupon = merchantCouponRepository.findOne(couponId);
            if (coupon == null) {
                jr.errorParam("非法票券", log);
                return;
            }
            PageResult productPage = new PageResult();
            MerchantCoupon merchantCoupon = merchantCouponRepository.findOne(couponId);
            if (CouponUseScope.ALL_PRODUCT == merchantCoupon.getUseScope()) {
                productPage = merchantProductRepository.findByMerchantPage(merchantCoupon.getMerchantId(), Whether.NO, ProductStatus.SELLING, this.getPage(productDto.getPageNo(), productDto.getPageSize()));
            } else if (CouponUseScope.PART_PRODUCT == merchantCoupon.getUseScope()) {
                List<CouponMerchantProducts> couponMerchantProductsList = couponMerchantProductsRepository.findByCouponIdAndIsDelete(couponId, Whether.NO);
                List<Long> productIdList = couponMerchantProductsList.stream().map(CouponMerchantProducts::getProductId).collect(Collectors.toList());
                productPage = merchantProductRepository.findByIdInAndIsDeletePage(productIdList, customerDto.getMallId(), Whether.NO, this.getPage(productDto.getPageNo(), productDto.getPageSize()));
            }
            jr.setData(productPage);

            //记录浏览数据
            ProductEventDto productEventDto = new ProductEventDto();
            productEventDto.setEventType(ProductEventType.VIEWED);
            productEventDto.setCustomerId(customerDto.getId());
            productEventDto.setCustomerName(customerDto.getNickName());
            productEventHelper.view(productPage.data, productEventDto);

        };
        return doing.go(request, log);
    }

    /**
     * @api {get} /api/v2/product/explosion/list 爆款小程序 查询爆款产品列表
     * @apiGroup product
     * @apiParam {Long} pageNo 页
     * @apiParam {Long} pageSize 页记录数
     * @apiSuccess {Long} id 产品ID
     * @apiSuccess {Date} dateCreated 创建时间
     * @apiSuccess {Date} lastUpdated 更新时间
     * @apiSuccess {Long} version 版本
     * @apiSuccess {String} type 产品类型
     * @apiSuccess {String} name 产品名称
     * @apiSuccess {BigDecimal} basePrice 原价
     * @apiSuccess {BigDecimal} sellPrice 出售价
     * @apiSuccess {Long} quantity 库存量
     * @apiSuccess {BigDecimal} carriage 运费
     * @apiSuccess {boolean} refundable 是否支持过期退
     * @apiSuccess {String} barcode 产品编码
     * @apiSuccess {boolean} sellnow 是否立即开售
     * @apiSuccess {Date} dateSelling 开售时间
     * @apiSuccess {Long} limitCount 限购数
     * @apiSuccess {String} logoUrl LOGO图
     * @apiSuccess {String} logoUrls LOGO图 多张
     * @apiSuccess {String} note 卖点介绍
     * @apiSuccess {String=SELLING("在售"), SOLDOUT("已下架"), EXPIRED("已过期"), DELETED("已删除"), WAIT_APPLY("待申请"), WAIT_AUDIT("待审核"), AUDIT_PASS("审核通过"), AUDIT_FAIL("审核不通过")} status 产品状态
     * @apiSuccess {Long} mallId 平台ID
     * @apiSuccess {Long} merchantId 商家ID
     * @apiSuccess {String} serveRate 服务费比率
     * @apiSuccess {String=SHOP_PICKUP("到店自取"), SHIPPING("物流"), SHOP_PICKUP_AND_SHIPPING("物流及到店自取")} shippingType 支持的物流类型
     * @apiSuccess {String} resellFee 分销佣金
     * @apiSuccess {String} shareFee 分享返利
     * @apiSuccess {String} merchantName 产品所属商家名称
     * @apiSuccess {Boolean} recommend 是否在分销市场展示
     * @apiSuccess {Integer} totalCount 总记录数
     * @apiSuccess {Integer} totalPage 总页数
     * @apiSuccess {Integer} pageNo 当前页
     * @apiSuccess {Integer} pageSize 每页记录数
     * @apiSuccessExample {json} Success-Response:
     * <p>
     * {
     *     "code":"1",
     *     "desc":"成功",
     *     "data":{
     *         "data":[
     *             {
     *                 "id":1773,
     *                 "dateCreated":"2017-06-20 15:07:54",
     *                 "lastUpdated":"2017-07-18 16:56:36",
     *                 "type":"GOODS",
     *                 "name":"建华毛钱",
     *                 "basePrice":2,
     *                 "sellPrice":1,
     *                 "carriage":0,
     *                 "refundable":false,
     *                 "barcode":"",
     *                 "sellnow":true,
     *                 "dateSelling":"2017-06-20 15:07:55",
     *                 "limitCount":0,
     *                 "logoUrl":"http://uploads.rockcent.com//dev/product/face/20172/2494614229b04cf6b6-6263-46be-976c-ee2e201673fe",
     *                 "logoUrls":[
     *                     "["http://uploads.rockcent.com//dev/product/face/20172/2494614229b04cf6b6-6263-46be-976c-ee2e201673fe"]"
     *                 ],
     *                 "note":"123456543",
     *                 "status":"SELLING",
     *                 "mallId":51,
     *                 "merchantId":129,
     *                 "serveRate":"3",
     *                 "shippingType":"SHIPPING",
     *                 "resellFee":0.5,
     *                 "shareFee":0.2,
     *                 "merchantName":"歌力思",
     *                 "favourite":"NO",
     *                 "settleAmount":0,
     *                 "serveFee":0,
     *                 "productQuantityId":866,
     *                 "productClientType":"EXPLOSION",
     *                 "sortNum":1,
     *                 "recommend":false
     *             }
     *         ],
     *         "totalCount":7,
     *         "totalPage":1,
     *         "pageNo":0,
     *         "pageSize":10
     *     }
     * }
     */
    @RequestMapping(value = Routes.PRODUCT_EXPLOSION_LIST, method = RequestMethod.GET)
    @ResponseBody
    public JsonResult explosionList(Integer pageNo, Integer pageSize, HttpServletRequest request) {
        CustomerDto customerDto = customerHelper.getSession(request);
        RestDoing doing = jsonResult -> {
            jsonResult.data = productSrv.findMiniExplosionProducts(customerDto.getMallId(), ProductClientType.EXPLOSION, this.getPage(pageNo, pageSize));
        };
        return doing.go(request, log);
    }
}